home *** CD-ROM | disk | FTP | other *** search
/ Sounds Terrific 2 / Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso / archives / amiga / tracker_4_31.lzh / tracker / automaton.c < prev    next >
C/C++ Source or Header  |  1995-05-11  |  6KB  |  240 lines

  1. /* automaton.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* $Id: automaton.c,v 4.17 1995/05/11 12:30:20 espie Exp espie $
  6.  * $Log: automaton.c,v $
  7.  * Revision 4.17  1995/05/11  12:30:20  espie
  8.  * Corrected DELAY PATTERN effect.
  9.  *
  10.  * Revision 4.16  1995/03/11  21:40:02  espie
  11.  * Modified jump pattern to work...
  12.  *
  13.  * Revision 4.15  1995/03/03  14:23:28  espie
  14.  * Spurious bug fixed.
  15.  *
  16.  * Revision 4.14  1995/03/01  15:24:51  espie
  17.  * Block length was hardcoded.
  18.  *
  19.  * Revision 4.13  1995/02/21  21:13:16  espie
  20.  * Cleaned up source. Moved minor pieces of code around.
  21.  *
  22.  * Revision 4.12  1995/02/21  17:54:32  espie
  23.  * Internal problem: buggy RCS. Fixed logs.
  24.  *
  25.  * Revision 4.6  1995/02/01  16:39:04  espie
  26.  * Includes moved to defs.h
  27.  *
  28.  * Revision 4.2  1994/08/23  18:19:46  espie
  29.  * Added speedmode option
  30.  * Abstracted IO calls.
  31.  * Use display_pattern.
  32.  * Fixed up repeat code, should work better now.
  33.  * Fixed bug with bad loops.
  34.  * Modified the way set_speed works.
  35.  * Corrected stupid bug (run_in_fg)
  36.  * Added bg/fg test.
  37.  * General cleanup
  38.  * Added finetune.
  39.  * Protracker commands.
  40.  *
  41.  * Revision 2.16  1992/11/17  17:15:37  espie
  42.  * New output for new interface
  43.  * Modified repeat logic: now works irregardless of repeat points.
  44.  * start
  45.  *
  46.  * Revision 2.8  1992/07/14  14:23:41  espie
  47.  * Changed fine speed command and comments.
  48.  * Added two level of fault tolerancy.
  49.  */
  50.      
  51.  
  52.      
  53. #include "defs.h"
  54. #include "song.h"
  55. #include "channel.h"
  56. #include "extern.h"
  57. #include "prefs.h"
  58.      
  59. ID("$Id: automaton.c,v 4.17 1995/05/11 12:30:20 espie Exp espie $")
  60.      
  61.  
  62. /* set up the automaton so that I haven't got through patterns 
  63.  * #from to #to
  64.  */
  65. LOCAL void clear_repeats(a, from, upto)
  66. struct automaton *a;
  67. int from, upto;
  68.    {
  69.    int i;
  70.  
  71.    for (i = from; i <= upto; i++)
  72.       a->gonethrough[i] = FALSE;
  73.    }
  74.  
  75. /* set up the automaton so that I haven't got through any patterns
  76.  */
  77. LOCAL void reset_repeats(a)
  78. struct automaton *a;
  79.    {
  80.    clear_repeats(a, 0, a->info->length);
  81.    a->gonethrough[a->info->length] = TRUE;
  82.    }
  83.  
  84. /* update the pattern to play in the automaton. Checks that the pattern 
  85.  * actually exists. Handle repetitions as well.
  86.  */
  87. LOCAL void set_pattern(a)
  88. struct automaton *a;
  89.    {
  90.    int p;
  91.  
  92.  
  93.    if (a->pattern_num >= a->info->length)
  94.       {
  95.       error = UNRECOVERABLE;
  96.       return;
  97.       }
  98.  
  99.    if (a->gonethrough[a->pattern_num])
  100.       {
  101.       error = ENDED;
  102.       reset_repeats(a);
  103.       }
  104.    else
  105.       a->gonethrough[a->pattern_num] = TRUE;
  106.  
  107.       /* there is a level of indirection in the format,
  108.        * i.e., patterns can be repeated.
  109.        */
  110.    p = a->info->patnumber[a->pattern_num];
  111.    if (p >= a->info->maxpat)
  112.       {
  113.       error = UNRECOVERABLE;
  114.       return;
  115.       }
  116.  
  117.    display_pattern(a->pattern_num, a->info->length, p);
  118.  
  119.    a->pattern = a->info->pblocks + p;
  120.    }
  121.  
  122. /* initialize all the fields of the automaton necessary
  123.  * to play a given song.
  124.  */
  125. void init_automaton(a, song, start)
  126. struct automaton *a;
  127. struct song *song;
  128. int start;
  129.    {
  130.    a->info = &song->info;
  131.    a->pattern_num = start;    /* first pattern */
  132.  
  133.    a->loop_note_num = 0;
  134.    a->loop_counter = 0;
  135.    a->delay_counter = 0;
  136.  
  137.    reset_repeats(a);
  138.  
  139.    a->note_num = 0;           /* first note in pattern */
  140.    a->counter = 0;            /* counter for the effect tempo */
  141.    a->speed = NORMAL_SPEED;   /* this is the default effect tempo */
  142.    a->finespeed = NORMAL_FINESPEED;    /* this is the fine speed 
  143.                                          * (100%=NORMAL_FINESPEED) */
  144.    a->do_stuff = DO_NOTHING;  /* some effects affect the automaton,
  145.                                * we keep them here.  */
  146.    error = NONE;              /* Maybe we should not reset errors at
  147.                                * this point ?  */
  148.    set_pattern(a);
  149.    }
  150.  
  151. /* get to the next pattern, and display stuff 
  152.  */
  153. LOCAL void advance_pattern(a)
  154. struct automaton *a;
  155.    {
  156.    if (++a->pattern_num >= a->info->length)
  157.         {
  158.         error = ENDED;
  159.         reset_repeats(a);
  160.       a->pattern_num = 0;
  161.         }
  162.    set_pattern(a);
  163.    a->note_num = 0;
  164.    }
  165.  
  166.         
  167.  
  168. /* process all the stuff which we need to advance in the song,
  169.  * including set_speed, set_skip, set_fastskip, and set_loop.
  170.  */
  171. void next_tick(a)
  172. struct automaton *a;
  173.    {
  174.       /* there are three classes of speed changes:
  175.        * 0 does nothing. (should stop for genuine protracker)
  176.        * <32 is the effect speed (resets the fine speed).
  177.        * >=32 changes the finespeed, default 125
  178.        */
  179.     if (a->do_stuff & (SET_SPEED | SET_FINESPEED) == SET_SPEED | SET_FINESPEED)
  180.         switch(get_pref_scalar(PREF_SPEEDMODE))
  181.             {
  182.         case FINESPEED_ONLY:
  183.             a->do_stuff &= ~SET_SPEED;
  184.             break;
  185.         case SPEED_ONLY:
  186.             a->do_stuff &= ~SET_FINESPEED;
  187.         default:
  188.             break;
  189.             }
  190.         
  191.    if ((a->do_stuff & SET_SPEED) && (a->do_stuff & SET_FINESPEED))
  192.       {
  193.       a->speed = a->new_speed;
  194.       a->finespeed = a->new_finespeed; 
  195.       }
  196.    else if (a->do_stuff & SET_FINESPEED)
  197.       {
  198.       a->finespeed = a->new_finespeed;
  199.       }
  200.    else if (a->do_stuff & SET_SPEED)
  201.       {
  202.       a->speed = a->new_speed;
  203.       a->finespeed = NORMAL_FINESPEED;
  204.       }
  205.  
  206.    if (++a->counter >= a->speed)
  207.       {
  208.       a->counter = 0;
  209.                 /* if we are in delay mode, count down delay */
  210.         if (a->delay_counter > 0)
  211.             a->delay_counter--;
  212.             /* get to next tick ONLY if no delay */
  213.         if (a->delay_counter == 0)
  214.             {
  215.                 /* loop: may change note in pattern right away */
  216.             if (a->do_stuff & JUMP_PATTERN)
  217.                 a->note_num = a->loop_note_num;
  218.             else if (a->do_stuff & SET_FASTSKIP)
  219.                 {
  220.                 a->pattern_num = a->new_pattern;
  221.                 set_pattern(a);
  222.                 a->note_num = 0;
  223.                 }
  224.             else if (a->do_stuff & SET_SKIP)
  225.                 {
  226.                 advance_pattern(a);
  227.                 a->note_num = a->new_note;
  228.                 }
  229.             else
  230.                 {
  231.             if (++a->note_num >= a->info->plength)
  232.                advance_pattern(a);
  233.                 }
  234.             a->do_stuff = DO_NOTHING;
  235.          }
  236.       }
  237.    }
  238.  
  239.  
  240.